/*
  Copyright 2002-2003 The University of Texas at Austin
  
    Authors: Anthony Thane <thanea@ices.utexas.edu>
             Vinay Siddavanahalli <skvinay@cs.utexas.edu>
    Advisor: Chandrajit Bajaj <bajaj@cs.utexas.edu>

  This file is part of Volume Rover.

  Volume Rover is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  Volume Rover is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with iotree; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifndef XOOMEDIN_H
#define XOOMEDIN_H

#include <QAction>
#include <QFrame>
#include <QPainter>

#include "../../renderer/colormap.h"
#include "../../renderer/alphamap.h"
#include "../../renderer/transfermap.h"
#include "../../renderer/IsocontourMap.h"

using namespace PBVP;

class XoomedIn : public QFrame 
{
	Q_OBJECT
public:
	/// <summary>
	/// 
	/// </summary>
	/// <param name="colorTableInformation"></param>
	/// <param name="parent"></param>
	/// <param name="name"></param>
	XoomedIn( TransferMap* transferMap, QWidget *parent, const char *name );

	/// <summary>
	/// 
	/// </summary>
	virtual ~XoomedIn();

	/// <summary>
	/// 
	/// </summary>
	/// <param name="minVal"></param>
	/// <param name="maxVal"></param>
	void setValExtents( double minVal, double maxVal );

	/// <summary>
	/// 
	/// </summary>
	/// <param name="index"></param>
	/// <returns>bool</returns>
	bool removeIsocontourBar(int index);

	/// <summary>
	/// 
	/// </summary>
	/// <param name="setAlphaMapVisible"></param>
	void setDrawAlphaMap( bool setAlphaMapVisible );

protected:
	QString tip( const QPoint & p );

	QRect getMyRect() const;

	QPoint transformToScreen(const QRect& rect, double density, double alpha) const;
	QPoint transformToScreen(const QRect& rect, int density, int alpha) const;

	int getIntDensity(const QRect& rect, double density) const;
	int getIntAlpha(const QRect& rect, double alpha) const;

	double getNormalizedDensity(const QRect& rect, const QPoint& source) const;
	double getNormalizedAlpha(const QRect& rect, const QPoint& source) const;

	int getIntDensity(const QRect& rect, const QPoint& source) const;
	int getIntAlpha(const QRect& rect, const QPoint& source) const;

	inline int mapToPixel(double input, int start, int end) const;
	inline double mapToDouble(int input, int start, int end, double min=0.0, double max=1.0) const;
	inline int possibleFlip(int input, int start, int end) const;


	virtual void paintEvent(QPaintEvent *);

	// virtual void drawContents( QPainter* painter );

	void drawColorMap( QPainter* painter, QRect rect );
	void drawColorBar( QPainter* painter, QRect rect, int index );

	void drawIsocontourBar( QPainter* painter, QRect rect, int index );

	void drawAlphaNode( QPainter* painter, QRect rect, int index );
	void drawAlphaMap( QPainter* painter, QRect rect );

	void drawContourSpectrum( QPainter* painter, QRect rect );
//	void drawContourTree( QPainter* painter, QRect rect );
	inline void normalizeFunc( float *func );

	inline void normalizeFunc( float *func, int len, float & min, float & max);
	inline float getSpecFuncValue( int func, double density );


	TransferMap* m_TransferMap;

	double m_RangeMin;
	double m_RangeMax;
	double m_MinVal;
	double m_MaxVal;

	float m_SpecFuncsMin[5];
	float m_SpecFuncsMax[5];


	enum MOVEMODE {DRAG_MOVE, NO_MOVE};

	enum SELECTEDTYPE {ALPHA_NODE, COLOR_NODE, ISOCONTOUR_NODE, NO_NODE};

	void showPopup(const QPoint& point);

	MOVEMODE m_MoveMode ;
	SELECTEDTYPE m_SelectedType;
	int m_SelectedNode ;
	
	float *m_SpecIsoval;
	float *m_SpecArea;
	float *m_SpecMinVol;
	float *m_SpecMaxVol;
	float *m_SpecGradient;
//	CTVTX *m_CTVerts;
//	CTEDGE *m_CTEdges;
	int m_NumCTVerts;
	int m_NumCTEdges;
	bool m_DrawContourSpec;
	bool m_DrawContourTree;
	bool m_DrawAlphaMap;

	/// <summary>
	/// Events handled by the control
	/// </summary>
	/// <param name="q"></param>
	virtual bool event(QEvent *event);
	virtual void mouseMoveEvent( QMouseEvent* q );
	virtual void mousePressEvent( QMouseEvent* q );
	virtual void mouseReleaseEvent( QMouseEvent* q );
	virtual void contextMenuEvent( QContextMenuEvent* e);

	bool selectNodes( int x, int y );

	bool getColorNodesHorizontal( int x, int y, double* r, double* g, double* b, double* density );
	bool getIsocontourNodesHorizontal( int x, int y, double* density );
	bool getAlphaNodesHorizontal( int x, int y, double* alpha, double* density );
	double getDensityHorizontal( double x );

signals:
	void isocontourNodeChanged( int index, double isovalue, double R, double G, double B );
	void isocontourNodeColorChanged( int index, double R, double G, double B );
	void isocontourNodeExploring( int index, double isovalue );
	void isocontourNodeAdded( int index, double isovalue, double R, double G, double B);
	void isocontourNodeDeleted( int index );
	void isocontourNodeSaved( int index );

	void acquireContourSpectrum();
	void acquireContourTree();

	void functionChanged( );
	void functionExploring( );

	void everythingChanged();

	void selectedColorNode();
	void selectedIsocontourNode( int index, double isovalue );
	void selectedAlphaNode();

public slots:
	void setMin( double min );
	void setMax( double max );

	void setSpectrumFunctions( float *isoval, float *area, float *min_vol, float *max_vol, float *gradient );

	/// <summary>
	/// Load Transfer map from a file
	/// </summary>
	void loadMap();

	/// Overloaded loadMap() function
	void loadMap(const QString& fname);

	/// <summary>
	/// Save transfer map to a file
	/// </summary>
	void saveMap();
	
	//	void setCTGraph(int numVerts, int numEdges, CTVTX* verts, CTEDGE* edges);
	
	///
	void addColorNode();
	
	/// 
	void addAlphaNode();
	
	///
	void addContourNode();
	
	///
	void editSelectedNode();
	
	///
	void deleteSelectedNode();

private:
	QAction *loadMapAction;
	QAction *saveMapAction;
	QAction *addColorAction;
	QAction *addAlphaAction;
	QAction *addContourAction;
	QAction *editNodeAction;
	QAction *deleteNodeAction;

	QMenu *popupMenu;
	QMenu *addNodeMenu;

	/// Current mouse position
	QPoint m_Positon;

	/// <summary>
	/// 
	/// </summary>
	/// <param name="x"></param>
	/// <param name="y"></param>
	/// <returns>bool</returns>
	bool selectColorNodes( int x, int y );
	/// <summary>
	/// 
	/// </summary>
	/// <param name="x"></param>
	/// <param name="y"></param>
	/// <returns>bool</returns>
	bool selectIsocontourNodes( int x, int y );
	/// <summary>
	/// 
	/// </summary>
	/// <param name="x"></param>
	/// <param name="y"></param>
	/// <returns>bool</returns>
	bool selectAlphaNodes( int x, int y );
	/// <summary>
	/// 
	/// </summary>
	/// Not implemented
	/// <param name="x"></param>
	/// <param name="y"></param>
	/// <returns>bool</returns>
	bool selectCTEdge( int x, int y );
};

#endif
